﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using OhioState.Tiling;

namespace OhioState.Tiling
{
    class SpriteTilingBuilder : ITilingBuilder<Sprite>
    {
        public float tStart
        {
            get;
            set;
        }
        public float tEnd
        {
            get;
            set;
        }
        public SpriteTilingBuilder(SpriteTileSet tileSet, int numberOfHorizontalTiles, float aspectRatio, float t1, float t2)
        {
            function = TestCurve;
            this.tileSet = tileSet;

            this.numberOfHorizontalTiles = numberOfHorizontalTiles;
            this.numberOfVerticalTiles = (int)(numberOfHorizontalTiles * aspectRatio);
            this.tStart = t1;
            this.tEnd = t2;
        }
        /// <summary>
        /// Determine the layout of the tiling and the parameter's range for the input function
        /// </summary>
        /// <param name="tileSet"></param>
        /// <param name="curve"> The function to draw on the screen</param>
        /// <param name="numberOfHorizontalTiles"> The number of horizontal tiles in the tiling</param>
        /// <param name="aspectRatio">To compute the number of vertical tiles in the tiling</param>
        /// <param name="t1">Parameter starts at t1</param>
        /// <param name="t2">Parameter ends at t1</param>
        public SpriteTilingBuilder(SpriteTileSet tileSet, Func<float, float> curve, int numberOfHorizontalTiles, float aspectRatio, float t1, float t2)
        {
            if (curve != null)
                function = curve;
            this.tileSet = tileSet;
            this.numberOfHorizontalTiles = numberOfHorizontalTiles;
            this.numberOfVerticalTiles = (int)(numberOfHorizontalTiles * aspectRatio);
            this.tStart = t1;
            this.tEnd = t2;
        }
        
        
        public static float TestCurve(float t)
        {
            return 4.0f * (float)Math.Cos(t / 5.0f * 3.1415f + 3.1415f * 0.5f) + 4.0f;
        }
        /// <summary>
        /// Tile the layout from bottom to top, the bottom will be dirt tile, the top will be 
        /// decided by the unfilled curve. 
        /// 100% unfilled == 75% dirt + 25% grass
        /// 75% unfilled = 50% dirt + 25% grass
        /// 50% unfilled = 25% dirt + 25% grass
        /// 25% unfilled = 0% dirt + 25% grass
        /// </summary>
        /// <returns></returns>
        public ITiling<Sprite> BuildTiling()
        {
            // Note the actual size of sprite is 1% of its texture's pixel size.
            float tileWidth = 0.01f * (float)tileSet.Width;
            float tileHeight = 0.01f * (float)tileSet.Height;


            List<SpriteTile> layout = new List<SpriteTile>();
            for (int i = 0; i < numberOfHorizontalTiles * numberOfVerticalTiles; i++)
                layout.Add(null);
               
            float step = (tEnd - tStart) / (float)numberOfHorizontalTiles;
            for (int i = 0; i < numberOfHorizontalTiles; i++)
            {
                float tp = tStart + (float)(i) * step + 0.5f * step;
                float val = function(tp);
                float h = 0;
                int j = 0;
               

                while (h < val)
                {
                    if (val - h <= tileHeight)
                    {
                        float remain = (val - h) / tileHeight;
                       
                        if (remain <= 0.25f && remain > 0.0f)
                        {
                            layout[j*numberOfHorizontalTiles + i] = tileSet.GetTile(0.25f,0.0f);
                           
                        }
                        else if (remain <= 0.5f && remain > 0.25f)
                        {
                            layout[j*numberOfHorizontalTiles + i] = tileSet.GetTile(0.25f,0.25f);
                           
                        }
                        else if (remain <= 0.75f && remain > 0.5f)
                        {
                            layout[j*numberOfHorizontalTiles + i] = tileSet.GetTile(0.25f,0.5f);
                           
                        }
                        else
                        {
                            layout[j*numberOfHorizontalTiles + i] = tileSet.GetTile(0.25f,0.75f);
                           
                        }
                        
                        break;
                    }
                    else
                    {
                        layout[j * numberOfHorizontalTiles + i] = tileSet.GetTile(0.0f, 1.0f);
                        j++;
                        if (j > numberOfVerticalTiles-1)
                            break;
                        h += tileHeight;
                    }
                }
            }
            SpriteTiling tiling = new SpriteTiling(layout, numberOfHorizontalTiles, numberOfVerticalTiles);
            return tiling;
        }
        private SpriteTileSet tileSet;

        private int numberOfHorizontalTiles;
        private int numberOfVerticalTiles;
        private Func<float, float> function = TestCurve;


    }
}
